/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.workbench.common.widgets.client.widget;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.TextBox;
import org.guvnor.common.services.shared.file.upload.FileManagerFields;
import org.guvnor.common.services.shared.file.upload.FileOperation;
import org.gwtbootstrap3.client.ui.Form;
import org.kie.workbench.common.widgets.client.resources.i18n.CommonConstants;
import org.uberfire.backend.vfs.Path;
import org.uberfire.ext.widgets.common.client.common.FileUpload;
import org.uberfire.ext.widgets.common.client.common.FileUploadFormEncoder;
/**
* This wraps a file uploader utility
*/
public class AttachmentFileWidget extends Composite {
private FileUpload up;
private final Form form = GWT.create(Form.class);
private final HorizontalPanel fields = GWT.create(HorizontalPanel.class);
private final TextBox fieldFilePath = getHiddenField(FileManagerFields.FORM_FIELD_PATH,
"");
private final TextBox fieldFileName = getHiddenField(FileManagerFields.FORM_FIELD_NAME,
"");
private final TextBox fieldFileFullPath = getHiddenField(FileManagerFields.FORM_FIELD_FULL_PATH,
"");
private final TextBox fieldFileOperation = getHiddenField(FileManagerFields.FORM_FIELD_OPERATION,
"");
private Command successCallback;
private Command errorCallback;
private String[] validFileExtensions;
private ClickHandler uploadButtonClickHanlder;
private FileUploadFormEncoder formEncoder = new FileUploadFormEncoder();
public AttachmentFileWidget() {
setup(false);
}
public AttachmentFileWidget(final String[] validFileExtensions) {
setup(false);
setAccept(validFileExtensions);
}
public AttachmentFileWidget(final boolean addFileUpload) {
setup(addFileUpload);
}
public AttachmentFileWidget(final String[] validFileExtensions,
final boolean addFileUpload) {
setup(addFileUpload);
setAccept(validFileExtensions);
}
void setup(boolean addFileUpload) {
up = createUploadWidget(addFileUpload);
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
formEncoder.addUtf8Charset(form);
// Validation is not performed in a SubmitHandler as it fails to be invoked with GWT-Bootstrap3. See:-
// - https://issues.jboss.org/browse/GUVNOR-2302 and
// - the underlying cause https://github.com/gwtbootstrap3/gwtbootstrap3/issues/375
// Validation is now performed prior to the form being submitted.
form.addSubmitCompleteHandler(new Form.SubmitCompleteHandler() {
@Override
public void onSubmitComplete(final Form.SubmitCompleteEvent event) {
if ("OK".equalsIgnoreCase(event.getResults())) {
executeCallback(successCallback);
showMessage(CommonConstants.INSTANCE.UploadSuccess());
} else {
executeCallback(errorCallback);
if (event.getResults().contains("org.uberfire.java.nio.file.FileAlreadyExistsException")) {
showMessage(org.uberfire.ext.widgets.common.client.resources.i18n.CommonConstants.INSTANCE.ExceptionFileAlreadyExists0(fieldFileName.getText()));
} else if (event.getResults().contains("DecisionTableParseException")) {
showMessage(CommonConstants.INSTANCE.UploadGenericError());
} else {
showMessage(org.uberfire.ext.widgets.common.client.resources.i18n.CommonConstants.INSTANCE.ExceptionGeneric0(event.getResults()));
}
}
reset();
}
});
fields.add(up);
fields.add(fieldFilePath);
fields.add(fieldFileName);
fields.add(fieldFileFullPath);
fields.add(fieldFileOperation);
form.add(fields);
initWidget(form);
}
//Package protected to support overriding for tests
FileUpload createUploadWidget(boolean addFileUpload) {
FileUpload up = new FileUpload(new org.uberfire.mvp.Command() {
@Override
public void execute() {
uploadButtonClickHanlder.onClick(null);
}
},
addFileUpload);
up.setName(FileManagerFields.UPLOAD_FIELD_NAME_ATTACH);
return up;
}
private void executeCallback(final Command callback) {
if (callback == null) {
return;
}
callback.execute();
}
public void reset() {
form.reset();
}
public void submit(final Path context,
final String fileName,
final String targetUrl,
final Command successCallback,
final Command errorCallback) {
submit(fileName,
context.toURI(),
FileOperation.CREATE,
"",
targetUrl,
successCallback,
errorCallback);
}
public void submit(final Path path,
final String targetUrl,
final Command successCallback,
final Command errorCallback) {
submit("",
"",
FileOperation.UPDATE,
path.toURI(),
targetUrl,
successCallback,
errorCallback);
}
void submit(final String fileName,
final String filePath,
final FileOperation operation,
final String fileFullPath,
final String targetUrl,
final Command successCallback,
final Command errorCallback) {
setCallbacks(successCallback,
errorCallback);
fieldFileName.setText(fileName);
fieldFilePath.setText(filePath);
fieldFileOperation.setText(operation.toString());
fieldFileFullPath.setText(fileFullPath);
form.setAction(targetUrl);
if (isValid()) {
form.submit();
}
}
//Package protected to support calls from tests
void setCallbacks(final Command successCallback,
final Command errorCallback) {
this.successCallback = successCallback;
this.errorCallback = errorCallback;
}
//Package protected to support calls/overriding for tests
boolean isValid() {
final String fileName = up.getFilename();
if (fileName == null || "".equals(fileName)) {
showMessage(CommonConstants.INSTANCE.UploadSelectAFile());
executeCallback(errorCallback);
return false;
}
if (validFileExtensions != null && validFileExtensions.length != 0) {
boolean isValid = false;
for (String extension : validFileExtensions) {
if (hasExtension(fileName,
extension)) {
isValid = true;
break;
}
}
if (!isValid) {
showMessage(CommonConstants.INSTANCE.UploadFileTypeNotSupported() + "\n\n" + CommonConstants.INSTANCE.UploadFileTypeSupportedExtensions0(makeValidFileExtensionsText()));
executeCallback(errorCallback);
return false;
}
}
return true;
}
private boolean hasExtension(String fileName,
String extension) {
String dotExtension = "." + extension;
// it ends with the correct extension
return fileName.endsWith(dotExtension)
// and the '.<extension>' is not the whole filename - which would make it a dot file without an extension
&& fileName.length() > dotExtension.length();
}
private String makeValidFileExtensionsText() {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < validFileExtensions.length; i++) {
sb.append("\"").append(validFileExtensions[i]).append(((i < validFileExtensions.length - 1 ? "\", " : "\"")));
}
return sb.toString();
}
private void setAccept(final String[] validFileExtensions) {
this.validFileExtensions = validFileExtensions;
final InputElement element = up.getElement().cast();
element.setAccept(makeAcceptString(validFileExtensions));
}
private String makeAcceptString(final String[] validFileExtensions) {
if (validFileExtensions == null || validFileExtensions.length == 0) {
return "";
}
final StringBuilder sb = new StringBuilder();
for (String fileExtension : validFileExtensions) {
sb.append(fileExtension).append(",");
}
sb.substring(0,
sb.length() - 1);
return sb.toString();
}
private TextBox getHiddenField(final String name,
final String value) {
final TextBox t = new TextBox();
t.setName(name);
t.setText(value);
t.setVisible(false);
return t;
}
public void addClickHandler(final ClickHandler clickHandler) {
this.uploadButtonClickHanlder = clickHandler;
}
public void setEnabled(boolean b) {
up.setEnabled(b);
}
public void showMessage(String message) {
Window.alert(message);
}
}